###
import abc  # 添加abc模块导入
from User_Management.config import PASSWORD_SALT, PASSWORD_HASH_ALGORITHM
from typing import List, Dict, Any
from User_Management.utils import generate_id
import sys
from datetime import datetime
import os

lms = None
if hasattr(sys.modules.get('__main__'), 'lms'):
    lms = sys.modules['__main__'].lms

class User(abc.ABC):  # 继承自abc.ABC
    """用户基类(抽象类,定义用户通用属性和方法)"""
    
    _all_users = []  # 类属性:所有用户列表
    
    def __init__(self, user_id: str, username: str, password: str, email: str, role: str, is_encrypted=False):
        self.user_id = user_id
        self.username = username
        # 根据is_encrypted参数决定是否加密密码
        if is_encrypted:
            self._password = password  # 直接使用已加密的密码
        else:
            self._password = self._encrypt_password(password)  # 加密存储
        self.email = email
        self.role = role
        if self not in User._all_users:
            User._all_users.append(self)

    def _caesar_cipher(self, text: str, shift: int = 3) -> str:
        """凯撒加密/解密函数"""
        result = ""
        for char in text:
            if char.isalpha():
                ascii_offset = ord('a') if char.islower() else ord('A')
                result += chr((ord(char) - ascii_offset + shift) % 26 + ascii_offset)
            else:
                result += char
        return result

    def _encrypt_password(self, raw_password: str) -> str:
        """私有方法:密码加密(使用盐值+凯撒加密,避免明文存储)"""
        combined = raw_password + PASSWORD_SALT
        return self._caesar_cipher(combined, shift=3)

    def _decrypt_password(self, encrypted_password: str) -> str:
        """私有方法:密码解密(用于验证)"""
        decrypted = self._caesar_cipher(encrypted_password, shift=-3)
        # 移除盐值部分
        if decrypted.endswith(PASSWORD_SALT):
            return decrypted[:-len(PASSWORD_SALT)]
        return decrypted

    def _verify_password(self, input_password: str) -> bool:
        """私有方法:密码验证"""
        encrypted_input = self._encrypt_password(input_password)
        return encrypted_input == self._password

    def login(self, username: str, password: str) -> bool:
        """用户登录方法"""
        if self.username == username:
            return self._verify_password(password)
        return False

    def change_password(self, old_password: str, new_password: str) -> bool:
        """修改密码方法"""
        if self._verify_password(old_password):
            self._password = self._encrypt_password(new_password)
            return True
        return False

    def to_dict(self):
        """学生类转换为字典以便序列化"""
        # 先调用父类方法获取基础属性
        return {
            "user_id": self.user_id,
            "username": self.username,
            "_password": self._password,  # 存储加密后的密码
            "email": self.email,
            "role": self.role
        }

    @classmethod
    def from_dict(cls, data: dict):
        """从字典创建用户对象(用于数据加载)"""
        user = cls.__new__(cls)
        user.user_id = data["user_id"]
        user.username = data["username"]
        user._password = data["password"]  # 直接使用已加密的密码
        user.email = data["email"]
        user.role = data["role"]
        return user

    @staticmethod
    def all_users() -> list:
        """获取所有用户列表"""
        if not hasattr(User, "_all_users"):
            User._all_users = []
        return User._all_users

    @staticmethod
    def register(username: str, password: str, email: str, role: str, **kwargs):
        """用户注册方法"""
        user_id = generate_id(prefix="USER_")

        # 2. 根据角色创建对应的用户对象
        if role.lower() == "student":
            new_user = Student(user_id, username, password, email, is_encrypted=False)
        elif role.lower() == "teacher":
            new_user = Teacher(user_id, username, password, email, is_encrypted=False)
        elif role.lower() == "admin":
            new_user = Administrator(user_id, username, password, email, is_encrypted=False)
        else:
            raise ValueError(f"无效的角色: {role}")

        # 3. 检查用户是否已存在(增强版)
        existing_users = User.all_users()
        existing_usernames = [user.username for user in existing_users]
    
        # 打印当前内存中的所有用户名,帮助调试
        print(f"当前内存中的用户数量: {len(existing_users)}")
        print(f"当前内存中的用户名列表: {existing_usernames}")
    
        # 检查是否存在完全匹配的用户名
        if username in existing_usernames:
            print(f"警告:用户名 '{username}' 已存在于内存中的用户列表中")
        
            # 获取所有重复的用户名(可能有多个相同用户名的用户对象)
            duplicate_users = [user for user in existing_users if user.username == username]
            print(f"发现 {len(duplicate_users)} 个名为 '{username}' 的用户对象")
        
            # 清理所有重复用户
            for user in duplicate_users:
                if user in User._all_users:
                    User._all_users.remove(user)
                    print(f"已移除重复用户: {user.user_id} (用户名: {user.username})")
        
            # 再次检查是否还有重名用户
            if any(user.username == username for user in User.all_users()):
                print(f"错误:清理后仍然存在名为 '{username}' 的用户")
                # 作为最后的手段,提供一个强制选项
                force_register = kwargs.get('force', False)
                if not force_register:
                    raise ValueError(f"用户名 '{username}' 已存在.如需强制注册,请使用force=True参数")
                else:
                    print(f"警告:强制注册名为 '{username}' 的用户")

        # 确保新用户被添加到_all_users列表
        if new_user not in User._all_users:
            User._all_users.append(new_user)
            print(f"已添加新用户: {username} (用户ID: {user_id})")

        return new_user

    def logout(self):
        """用户登出:重置登录状态(后续可结合 data_persistence 保存状态)"""
        print(f"用户 {self.username} 已登出.")
        # 若需记录登录状态,可添加 self.is_logged_in = False(需在 __init__ 中初始化)

    def update_profile(self, new_info):
        """更新个人信息:仅允许修改非敏感属性(邮箱、用户名),禁止直接改密码"""
        # new_info 为字典,格式如 {"email": "new@xxx.com", "username": "newname"}
        for key, value in new_info.items():
            if key == "email":
                self.email = value  # 直接修改邮箱
            elif key == "username":
                self.username = value  # 直接修改用户名
            else:
                print(f"不支持修改属性:{key}(仅允许修改邮箱、用户名)")
        print(f"用户 {self.user_id} 信息更新成功!")

    # ------------------------------
    # 抽象方法:强制子类实现(多态核心)
    # ------------------------------
    @abc.abstractmethod
    def view_dashboard(self):
        """抽象方法:查看个人仪表盘(不同角色显示不同内容)"""
        pass  # 子类必须重写,否则无法实例化

    @classmethod
    def load_all_users(cls, user_data: List[Dict[str, Any]]) -> None:
        """类方法:从数据加载所有用户(根据角色分不同子类实例化)"""
        # 清空现有用户列表
        cls._all_users = []
        
        for user_dict in user_data:
            user_id = user_dict.get("user_id")
            username = user_dict.get("username")
            # 修复:先尝试获取"_password",如果不存在再尝试获取"password"
            password = user_dict.get("_password") or user_dict.get("password")
            email = user_dict.get("email")
            role = user_dict.get("role")
            student_id = user_dict.get("student_id")
            # 关键修改:添加teacher_id的提取
            teacher_id = user_dict.get("teacher_id")
            
            if not all([user_id, username, password, email, role]):
                print(f"跳过无效用户数据: {user_dict}")
                continue
                
            # 使用is_encrypted=True参数避免双重加密
            if role == "student":
                user = Student(user_id, username, password, email, is_encrypted=True, student_id=student_id)
            elif role == "teacher":
                # 关键修改:传递teacher_id参数
                user = Teacher(user_id, username, password, email, is_encrypted=True, teacher_id=teacher_id)
            elif role == "admin":
                user = Administrator(user_id, username, password, email, is_encrypted=True)
            else:
                print(f"未知角色: {role}, 跳过用户 {username}")
                continue
                
            # 将用户添加到_all_users列表
            cls._all_users.append(user)
                
            print(f"加载用户: {username} ({role})")

    @classmethod
    def associate_users_with_courses(cls):
        """课程加载完成后,将用户与课程关联起来"""
        try:
            # 导入Course类
            # import importlib
            import json
            import os
            from Course_Management_and_Enrollment.course_task_classes import Course
        
            # Course = importlib.import_module('Course_Management_and_Enrollment.course_task_classes').Course
        
            # 直接从data.json文件中加载数据
            project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
            data_file_path = os.path.join(project_root, "data.json")
        
            data = {}
            if os.path.exists(data_file_path):
                with open(data_file_path, "r", encoding="utf-8") as file:
                    data = json.load(file)

            # 获取所有课程
            all_courses = Course.all_courses()
        
            # 遍历所有用户
            for user in cls._all_users:
                # 1. 为学生关联课程
                if isinstance(user, Student):
                    # 清空现有列表,避免重复
                    user.enrolled_courses = []
                
                    # 在data.json中查找该用户的选课信息
                    for user_data in data.get('users', []):
                        if user_data.get('user_id') == user.user_id:
                            enrolled_course_ids = user_data.get('enrolled_courses', [])
                        
                            # 获取所有课程
                            all_courses = Course.all_courses()
                        
                            # 将课程ID转换为课程对象并建立双向关联
                            for course_id in enrolled_course_ids:
                                for course in all_courses:
                                    if course.course_id == course_id:
                                        user.enrolled_courses.append(course)
                                        # 添加双向关联:将学生添加到课程的enrolled_students列表
                                        if user not in course.enrolled_students:
                                            course.enrolled_students.append(user)
                                        break
                            break
            
                # 2. 为教师关联管理的课程
                elif isinstance(user, Teacher):
                    # 清空现有列表
                    user.managed_courses = []
                
                    # 优先从data.json中获取教师负责的课程
                    managed_course_ids = []
                    for user_data in data.get('users', []):
                        if user_data.get('user_id') == user.user_id:
                            managed_course_ids = user_data.get('managed_courses', [])
                            break
                
                    # 方法1: 通过课程ID关联课程
                    for course_id in managed_course_ids:
                        for course in all_courses:
                            if course.course_id == course_id:
                                user.managed_courses.append(course)
                                course.teacher = user
                                break

                    # 方法2: 通过教师ID关联课程(作为后备方案)
                    if not user.managed_courses:
                        for course in all_courses:
                            if hasattr(course, 'teacher') and course.teacher and hasattr(course.teacher, 'teacher_id') and course.teacher.teacher_id == user.teacher_id:
                                user.managed_courses.append(course)
                            elif hasattr(course, 'teacher_id') and course.teacher_id == user.teacher_id:
                                user.managed_courses.append(course)
                                course.teacher = user
    
        except Exception as e:
            print(f"关联用户与课程时出错: {e}")

    @classmethod
    def all_users(cls) -> List["User"]:
        """类方法:返回所有用户实例(包含不同角色)"""
        return cls._all_users

class Student(User):
    # 修改构造函数定义,添加role参数并正确传递给父类
    def __init__(self, user_id, username, password, email, student_id=None, is_encrypted=True):
    # 正确调用父类构造函数,传递所有6个参数
        super().__init__(user_id, username, password, email,role="student", is_encrypted = is_encrypted)
        self.role = "student"  # 确保角色正确设置为student
        self.student_id = student_id or f"STU_{os.urandom(4).hex().upper()}"
        self.enrolled_courses = []
        self.grades = {}
        self.submitted_assignments = []
        self.is_active = True  # 添加活跃状态属性
        self.lms = None  # 初始化lms属性为None
        
    @property
    def name(self):
        return self.username  # 添加name属性的getter
    
    def to_dict(self):
        """学生类转换为字典以便序列化"""
        # 先调用父类方法获取基础属性
        result = super().to_dict()
        # 添加学生专属属性
        result.update({
            "student_id": self.student_id,
            "enrolled_courses": [course.course_id for course in self.enrolled_courses],
            "is_active": self.is_active
        })
        # 序列化成绩信息(只保存课程ID和分数)
        grades_dict = {}
        for course, score in self.grades.items():
            if hasattr(course, 'course_id'):
                grades_dict[course.course_id] = score
        result["grades"] = grades_dict
        
        # 序列化已提交作业信息
        submissions_list = []
        for submission in self.submitted_assignments:
            # 确保只保存可序列化的数据
            if isinstance(submission, dict):
                # 修复:保留所有必要的字段,包括content、course_id等
                safe_submission = {
                    key: value for key, value in submission.items()
                    if key in ['assignment_id', 'course_id', 'content', 'submit_time', 'is_late', 'score', 'status']
                }
                # 安全地转换时间对象为字符串,添加空值检查
                if 'submit_time' in safe_submission and safe_submission['submit_time'] is not None and hasattr(safe_submission['submit_time'], 'isoformat'):
                    safe_submission['submit_time'] = safe_submission['submit_time'].isoformat()
                submissions_list.append(safe_submission)
        result["submitted_assignments"] = submissions_list
        
        return result


    # ------------------------------
    # 多态实现:学生仪表盘(显示已选课程、成绩)
    # ------------------------------
    def view_dashboard(self):
        """学生仪表盘:显示个人信息、已选课程、平均成绩"""
        print("="*50)
        print(f"【学生仪表盘】- 学号:{self.student_id}")
        print(f"用户名:{self.username} | 邮箱:{self.email}")
        print(f"已选课程数:{len(self.enrolled_courses)}")
        for course in self.enrolled_courses:
            print(f"  - {course.course_name}(课程ID:{course.course_id})")
        # 计算平均成绩(若有成绩)
        if self.grades:
            avg_grade = sum(self.grades.values()) / len(self.grades)
            print(f"平均成绩:{avg_grade:.1f}")
        else:
            print("暂无成绩记录")
        print("="*50)

    # ------------------------------
    # 学生专属方法:选课与退课(关联 Yori 模块)
    # ------------------------------
    def enroll_course(self, course):
        """选课:添加 Course 实例到 enrolled_courses(需先验证合法性)"""
        # 1. 验证:课程是否已选、是否满员、课程状态是否已审核
        if course in self.enrolled_courses:
            print(f"已选课程:{course.course_name},无需重复选择!")
            return False
        if len(course.enrolled_students) >= course.max_students:
            print(f"课程 {course.course_name} 已满员(上限 {course.max_students} 人),无法选课!")
            return False
        # 添加课程状态验证
        if course.status != "approved":
            print(f"课程 {course.course_name} 尚未通过审核,无法选课!")
            return False
        # 2. 选课:添加课程到学生列表,并同步添加学生到课程的 enrolled_students(双向关联)
        self.enrolled_courses.append(course)
        course.enrolled_students.append(self)
        print(f"成功选课程:{course.course_name}(课程ID:{course.course_id})")
        return True

    def drop_course(self, course: object) -> bool:
        """学生退课
        
        Args:
            course: 要退的课程对象
        
        Returns:
            bool: 退课是否成功
        """
        # 检查是否已选该课程
        if course not in self.enrolled_courses:
            print(f"您未选该课程: {course.course_name}")
            return False
        
        # 移除课程关联
        self.enrolled_courses.remove(course)
        course._remove_student(self)
        
        # 删除相关成绩记录
        if self.user_id in self.grading_system.grade_records.get(course.course_id, {}):
            del self.grading_system.grade_records[course.course_id][self.user_id]
        
        print(f"已成功退课: {course.course_name}")
        return True
    
    def request_drop_course(self, course: object) -> bool:
        """申请退课(需要管理员审批)
        
        Args:
            course: 要退的课程对象
        
        Returns:
            bool: 申请是否提交成功
        """
        # 检查是否已选该课程
        if course not in self.enrolled_courses:
            print(f"您未选该课程: {course.course_name}")
            return False
        
        # 创建退课申请(实际应用中应保存到系统中)
        print(f"退课申请已提交: {course.course_name},等待管理员审批.")
        
        # 这里应该有保存退课申请的逻辑,为简化示例,暂不实现
        return True

    # ------------------------------
    # 学生专属方法:提交作业与查看成绩(关联 Serein 模块)
    # ------------------------------
    # 在submit_assignment方法中修改数据更改标记逻辑
    def submit_assignment(self, assignment, content):
        """提交作业"""
        try:
            # 检查是否已提交
            assignment_id = getattr(assignment, 'assignment_id', getattr(assignment, 'assignable_id', None))
            if not assignment_id:
                return False, "无法获取作业ID"
        
            for submitted in self.submitted_assignments:
                if submitted["assignment_id"] == assignment_id:
                    return False, "您已经提交过此作业"
        
            # 调用作业的submit方法
            success, msg = assignment.submit(self, content)
            if not success:
                return False, msg
        
            # 记录提交信息到学生对象
            submission_info = {
                "assignment_id": assignment_id,
                "course_id": assignment.course.course_id,
                "teacher_id": assignment.course.teacher.teacher_id if assignment.course and assignment.course.teacher else None,
                "submit_time": datetime.now(),
                "status": "submitted",  # 修改为英文状态值,与系统其他部分保持一致
                "content": content
            }
            self.submitted_assignments.append(submission_info)
        
            # 标记数据已更改
            if hasattr(self, 'mark_data_changed'):
                self.mark_data_changed()
            elif hasattr(self, "lms") and hasattr(self.lms, "mark_data_changed"):
                self.lms.mark_data_changed()
                if hasattr(self.lms, "save_data"):
                    self.lms.save_data(force=True)
        
            return True, "submit success"
        except Exception as e:
            return False, f"submit failed: {str(e)}"
    
    def view_my_grades(self):
        """查看个人成绩:按课程显示总成绩"""
        if not self.grades:
            print("暂无成绩记录!")
            return
        print("="*50)
        print(f"【我的成绩】- 学号:{self.student_id}")
        for course, grade in self.grades.items():
            print(f"课程:{course.course_name} | 总成绩:{grade}")
        print("="*50)

    def update_course_progress(self, course_id):
        """更新课程进度"""
        # 查找对应的课程对象
        target_course = None
        for course in self.enrolled_courses:
            if course.course_id == course_id:
                target_course = course
                break
        
        if not target_course:
            return
        
        # 计算课程进度
        total_assignments = len(target_course.course_assignments)
        if total_assignments == 0:
            return
    
        # 统计已提交的作业数
        submitted_count = 0
        for submission in self.submitted_assignments:
            assignment_id = submission.get("assignment_id")
            for course_assignment in target_course.course_assignments:
                if course_assignment.assignable_id == assignment_id:
                    submitted_count += 1
                    break
    
        # 计算进度百分比
        progress = (submitted_count / total_assignments) * 100
    
        # 确保从GradingSystem获取总成绩并更新到grades字典
        try:
            # 导入GradingSystem
            from Assignment_and_Grading.system_modules import GradingSystem
            # 获取成绩
            if hasattr(self, 'lms') and self.lms and hasattr(self.lms, 'grading_system'):
                total_score = self.lms.grading_system.calculate_course_grade(self, target_course)
                self.grades[target_course] = total_score
        except Exception as e:
            # 如果无法获取成绩,至少确保进度正确
            pass


    def view_my_progress(self, course):
        """查看单课程进度:需结合 Serein 模块的作业完成情况"""
        if course not in self.enrolled_courses:
            print(f"未选课程 {course.course_name},无法查看进度!")
            return
        # 1. 获取该课程的所有作业
        total_assignments = len(course.course_assignments)
        if total_assignments == 0:
            print(f"课程 {course.course_name} 暂无作业,进度:0%")
            return
        # 2. 统计已提交的作业数
        submitted_count = 0
        for submission in self.submitted_assignments:
            # 修改为访问字典的assignment_id键
            assignment_id = submission.get("assignment_id")
            for course_assignment in course.course_assignments:
                if course_assignment.assignable_id == assignment_id:
                    submitted_count += 1
                    break
        # 3. 计算进度百分比
        progress = (submitted_count / total_assignments) * 100
        print(f"【课程进度】- {course.course_name}")
        print(f"已提交作业:{submitted_count}/{total_assignments} | 进度:{progress:.1f}%")


class Teacher(User):
    def __init__(self, user_id, username, password, email, is_encrypted=False, teacher_id=None):
        # 1. 调用父类构造函数,role 固定为 "teacher"
        super().__init__(user_id, username, password, email, role="teacher", is_encrypted=is_encrypted)
        # 2. 教师专属属性
        # 关键修改:如果提供了teacher_id就使用它,否则生成新的
        self.teacher_id = teacher_id if teacher_id else generate_id(prefix="TCH_")  # 教师唯一ID
        self.managed_courses = []  # 存储教师负责的 Course 实例(关联 Yori 模块)
        self.created_assignments = []  # 存储教师创建的 Assignment 实例(关联 Serein 模块)
        self.created_courses = []  # 记录教师创建的课程ID

    def manage_course(self, course):
        """添加课程到教师的管理列表"""
        if course not in self.managed_courses:
            self.managed_courses.append(course)
            course.teacher = self
            return True
        return False
    
    def to_dict(self):
        """教师类转换为字典以便序列化"""
        # 先调用父类方法获取基础属性
        result = super().to_dict()
        # 添加教师专属属性
        result.update({
            "teacher_id": self.teacher_id,
            "managed_courses": [course.course_id for course in self.managed_courses if hasattr(course, 'course_id')],
            "created_courses": self.created_courses
        })
        
        # 序列化已创建作业信息(只保存ID)
        created_assignments_ids = []
        for assignment in self.created_assignments:
            if hasattr(assignment, 'assignment_id'):
                created_assignments_ids.append(assignment.assignment_id)
            elif hasattr(assignment, 'assignable_id'):
                created_assignments_ids.append(assignment.assignable_id)
        result["created_assignments"] = created_assignments_ids
        
        return result


    # ------------------------------
    # 多态实现:教师仪表盘(显示管理的课程、待批改作业)
    # ------------------------------
    def view_student_assignment(self, assignment, student):
        """查看学生提交的作业内容
        
        Args:
            assignment: 作业对象
            student: 学生对象
            
        Returns:
            tuple: (是否成功查看, 消息或作业内容)
        """
        try:
            # 1. 验证权限
            if assignment not in self.created_assignments:
                return False, f"无权限查看作业 {assignment.assignment_title}(非你创建的作业)!"
            
            # 2. 验证学生是否选了该课程
            is_enrolled = False
            for enrolled_student in assignment.course.enrolled_students:
                if enrolled_student.user_id == student.user_id:
                    is_enrolled = True
                    break
            
            if not is_enrolled:
                return False, f"学生 {student.username} 未选该课程!"
                
            # 3. 检查学生是否提交了作业
            student_id = getattr(student, 'student_id', getattr(student, 'user_id', str(student)))
            if not hasattr(assignment, 'submissions') or student_id not in assignment.submissions:
                return False, f"学生 {student.username} 尚未提交该作业!"
            
            # 4. 获取作业内容
            submission = assignment.submissions[student_id]
            content = submission.get("content", "无提交内容")
            submit_time = submission.get("submit_time")
            is_late = submission.get("is_late", False)
            score = submission.get("score")
            
            # 5. 格式化返回信息
            result = {
                "content": content,
                "submit_time": submit_time,
                "is_late": is_late,
                "score": score,
                "student_name": student.username,
                "assignment_title": assignment.assignment_title
            }
            
            return True, result
        except Exception as e:
            return False, f"查看作业时出错: {str(e)}"


    def view_dashboard(self):
        print("="*50)
        print(f"【教师仪表盘】- 教师ID:{self.teacher_id}")
        print(f"管理课程数:{len(self.managed_courses)}")
        # 修复:使用正确的 submissions 属性来统计待批改作业
        pending_grading = 0
        for assignment in self.created_assignments:
            # 使用实际存储提交数据的 submissions 属性
            # 只统计未评分的提交
            if hasattr(assignment, 'submissions'):
                for submission in assignment.submissions.values():
                    if submission.get('score') is None:
                        pending_grading += 1
        print(f"待批改作业数:{pending_grading}")
        print("="*50)

    # ------------------------------
    # 教师专属方法:课程管理(创建/修改/删除,关联 Yori 模块)
    # ------------------------------
    def create_course(self, course_info):
        """创建课程:course_info 为字典(如 {"name": "Python OOP", "desc": "...", "max_students": 30})"""
        # 1. 导入 Course 类(Yori 模块的核心类)
        # 使用importlib进行动态导入,避免相对导入问题
        import importlib
        Course = importlib.import_module('Course_Management_and_Enrollment.course_task_classes').Course
        # 2. 创建 Course 实例(course_id 由工具函数生成)
        course = Course(
            course_id=generate_id(prefix="COURSE_"),
            course_name=course_info["name"],
            course_description=course_info.get("desc", "无描述"),
            teacher=self,  # 课程关联当前教师
            max_students=course_info.get("max_students", 20)
        )
        # 3. 添加到教师的管理课程列表
        self.managed_courses.append(course)
        print(f"成功创建课程:{course.course_name}(课程ID:{course.course_id})")

        if hasattr(self, "lms") and hasattr(self.lms, "mark_data_changed"):

            self.lms.mark_data_changed()

        return course

    def modify_course(self, course, new_info):
        """修改课程:new_info 为字典(如 {"name": "新名称", "max_students": 40})"""
        from Course_Management_and_Enrollment.course_task_classes import Course

        # 1. 验证:课程是否属于当前教师
        if course not in self.managed_courses:
            print(f"无权限修改课程 {course.course_name}(非你管理的课程)!")
            print(f"当前教师管理的课程: {[c.course_name for c in self.managed_courses]}")
            return False
        # 2. 修改课程属性(仅允许修改名称、描述、最大学生数)
        if "name" in new_info:
            course.course_name = new_info["name"]
        if "desc" in new_info:
            course.course_description = new_info["desc"]
        if "max_students" in new_info:
            # 验证最大学生数是否大于当前已选人数
            if new_info["max_students"] < len(course.enrolled_students):
                print(f"修改失败:新上限 {new_info['max_students']} 小于当前学生数 {len(course.enrolled_students)}")
                return False
            course.max_students = new_info["max_students"]
        print(f"成功修改课程:{course.course_name}(课程ID:{course.course_id})")
        return True

    def delete_course(self, course):
        """删除课程:需先验证权限,再移除关联"""
        try:
            if course not in self.managed_courses:
                print(f"无权限删除课程 {course.course_name}(非你管理的课程)!")
                return False
    
            # 1. 同步删除学生选课记录
            # 获取所有选课学生的副本(避免在遍历时修改列表)
            enrolled_students = [] 
            if hasattr(course, 'get_enrolled_students'):
                enrolled_students = course.get_enrolled_students() 
            elif hasattr(course, "students"):
                enrolled_students = course.students.copy() if isinstance(course.students, list) else list(course.students)

            for student in enrolled_students:
                if hasattr(student, 'drop_course'):
                    student.drop_course(course)
                elif hasattr(student, 'enrolled_courses') and course in student.enrolled_courses:
                    student.enrolled_courses.remove(course)
                    if hasattr(course, '_remove_student'):
                        course._remove_student(student)

            if hasattr(course, 'assignments'):
                course.assignments = []  # 清空作业列表
            if hasattr(course, 'quizzes'):
                course.quizzes = []  # 清空测验列表
            # 清空成绩记录
            if hasattr(self, 'grading_system') and hasattr(self.grading_system, 'grade_records'):
                if course.course_id in self.grading_system.grade_records:
                    del self.grading_system.grade_records[course.course_id]

            # 3. 移除教师的管理列表
            self.managed_courses.remove(course)
    
            # 4. 如果LMS系统有该课程,也从系统中移除
            if hasattr(self, 'lms') and hasattr(self.lms, 'courses') and course in self.lms.courses:
                self.lms.courses.remove(course)
    
            if hasattr(self, "lms"):
                if hasattr(self.lms, "mark_data_changed"):
                    self.lms.mark_data_changed()
                # 添加直接保存数据的调用,确保数据被保存
                if hasattr(self.lms, "save_data"):
                    self.lms.save_data()
                    
            print(f"成功删除课程:{course.course_name}(课程ID:{course.course_id})")
            print("已同步删除学生选课记录与作业")

            return True
        except Exception as e:
            print(f"删除课程 {course.course_name} 时出错: {e}")
            return False


    # ------------------------------
    # 教师专属方法:作业与成绩管理(关联 Serein 模块)
    # ------------------------------
    def create_assignment(self, course, assignment_info, assignment_id=None, title=None, due_date=None, assignment_content=None):
        from Assignment_and_Grading.course_task_classes import Assignment
        from Progress_Tracking_CLI_DataPersistence.lms_main import LMS
        """创建作业:assignment_info 为字典(如 {"title": "OOP 作业", "content": "...", "due_date": "2024-12-31"})"""
        if course not in self.managed_courses:
            print(f"无权限为课程 {course.course_name} 创建作业(非你管理的课程)!")
            return None
        
        # 使用传入的参数创建作业实例
        if assignment_info:
            # 从assignment_info字典中获取数据
            assignment = Assignment(
                assignment_id=assignment_id or generate_id(prefix="ASSIGN_"),
                assignment_title=assignment_info.get("title", "未命名作业"),
                assignment_content=assignment_info.get("content", ""),
                due_date_str=assignment_info.get("due_date"),
                course=course,
                required_format=assignment_info.get("format", "text"),
                total_points=assignment_info.get("points", 100)
            )
        else:
            # 直接使用传入的参数
            assignment = Assignment(
                assignment_id=assignment_id or generate_id(prefix="ASSIGN_"),
                assignment_title=title or "未命名作业",
                assignment_content=assignment_content or "",
                due_date_str=due_date,
                course=course,
                required_format="text",
                total_points=100
            )
        
        # 关联到教师与课程
        # 重要修复: 确保created_assignments列表存在
        if not hasattr(self, 'created_assignments'):
            self.created_assignments = []
        self.created_assignments.append(assignment)
    
        # 确保course.course_assignments存在
        if hasattr(course, 'add_assignment'):
            course.add_assignment(assignment)
        else:
            if not hasattr(course, 'course_assignments'):
                course.course_assignments = []
            course.course_assignments.append(assignment)
    
        # 为作业创建与选课学生的关联
        # 初始化提交字典,为每个选课学生预留提交位置
        if not hasattr(assignment, 'submissions'):
            assignment.submissions = {}
    
        for student in course.enrolled_students:
            # 初始状态为未提交
            assignment.submissions[student.student_id] = {
                "status": "未提交",
                "score": None,
                "content": None,
                "submit_time": None,
                "is_late": False
            }
    
        # 修复数据变更标记逻辑
        # 尝试通过全局LMS实例标记数据变更
        if hasattr(LMS, 'instance') and LMS.instance:
            LMS.instance.mark_data_changed()
    
        return assignment

    def grade_assignment(self, assignment, student, score):
        """为学生的作业评分
    
        Args:
            assignment: 作业对象
            student: 学生对象
            score: 分数
        
        Returns:
            bool: 是否评分成功
        """
        try:
            # 1. 验证权限
            if assignment not in self.created_assignments:
                print(f"无权限批改作业 {assignment.assignment_title}(非你创建的作业)!")
                return False
        
            # 2. 验证学生是否选了该课程
            is_enrolled = False
            for enrolled_student in assignment.course.enrolled_students:
                if enrolled_student.user_id == student.user_id:
                    is_enrolled = True
                    break
        
            if not is_enrolled:
                print(f"学生 {student.username} 未选该课程,无法为其评分!")
                return False
            
            # 3. 检查学生是否提交了作业
            student_id = getattr(student, 'student_id', getattr(student, 'user_id', str(student)))
            if not hasattr(assignment, 'submissions') or student_id not in assignment.submissions:
                print(f"学生 {student.username} 尚未提交该作业!")
                return False
        
            # 4. 确保分数有效
            try:
                score_value = float(score)
                if score_value < 0 or score_value > getattr(assignment, 'total_points', 100):
                    print(f"无效的分数: {score_value}. 必须在0到{getattr(assignment, 'total_points', 100)}之间.")
                    return False
            except ValueError:
                print(f"无效的分数格式: {score}")
                return False
        
            # 5. 更新作业对象中的提交记录
            assignment.submissions[student_id]["score"] = score_value
            assignment.submissions[student_id]["graded_time"] = datetime.now()
            assignment.submissions[student_id]["graded_by"] = self.teacher_id
        
            # 6. 更新学生的submitted_assignments中的成绩
            for submission in student.submitted_assignments:
                if submission["assignment_id"] == getattr(assignment, 'assignment_id', getattr(assignment, 'assignable_id', None)):
                    submission["score"] = score_value
                    break
        
            # 7. 调用GradingSystem记录成绩
            from ..Assignment_and_Grading.system_modules import GradingSystem
            if hasattr(self, 'lms') and hasattr(self.lms, 'grading_system'):
                grading_system = self.lms.grading_system
            else:
                grading_system = GradingSystem(lms=self.lms if hasattr(self, 'lms') else None)
        
            # 记录成绩
            assignment_id = getattr(assignment, 'assignment_id', getattr(assignment, 'assignable_id', None))
            course_id = assignment.course.course_id
            grading_system.grade_assignment(student, assignment, score_value)
        
            # 8. 同步更新学生的总成绩
            course = assignment.course
            course_grade = grading_system.calculate_course_grade(student, course)
            if isinstance(course_grade, dict) and "final_score" in course_grade:
                student.grades[course] = course_grade["final_score"]
            elif isinstance(course_grade, (int, float)):
                student.grades[course] = course_grade
        
            # 9. 标记数据变更
            if hasattr(self, 'lms') and hasattr(self.lms, 'mark_data_changed'):
                self.lms.mark_data_changed()
        
            # 10. 记录操作日志
            log_message = f"教师 {self.teacher_id} 为学生 {student.student_id} 的作业 {assignment.title} 评分: {score_value}"
            if hasattr(self, 'lms') and hasattr(self.lms, 'log_activity'):
                self.lms.log_activity(log_message)
            print(log_message)
        
            return True
        except Exception as e:
            error_msg = f"评分过程中出错: {str(e)}"
            print(error_msg)
            return False

    def view_class_roster(self, course):
        """查看课程的学生名单"""
        if course not in self.managed_courses:
            print(f"无权限查看课程 {course.course_name} 的学生名单(非你管理的课程)!")
            return
        print(f"【课程学生名单】- {course.course_name}(共 {len(course.enrolled_students)} 人)")
        for idx, student in enumerate(course.enrolled_students, 1):
            print(f"{idx}. 学号:{student.student_id} | 用户名:{student.username} | 邮箱:{student.email}")

    def can_edit_course(self, course_id):
        return course_id in self.created_courses  # 仅允许编辑自己创建的课程


class Administrator(User):
    def __init__(self, user_id, username, password, email, is_encrypted=False):
        # 1. 调用父类构造函数,role 固定为 "admin"
        super().__init__(user_id, username, password, email, role="admin", is_encrypted=is_encrypted)
        # 2. 管理员专属属性
        self.admin_id = generate_id(prefix="ADMIN_")  # 管理员唯一ID
        self.system_users = []  # 存储系统所有用户(User 子类实例)
        self.all_courses = []  # 存储系统所有课程(Course 实例,关联 Yori 模块)
    # 多态实现:管理员仪表盘(显示系统统计)
    # ------------------------------
    def view_dashboard(self):
        print("="*50)
        print(f"【管理员仪表盘】- 管理员ID:{self.admin_id}")
        print(f"系统总用户数:{len(self.system_users)}")
        # 统计各角色用户数
        role_count = {"student": 0, "teacher": 0, "admin": 0}
        for user in self.system_users:
            role_count[user.role] += 1
        print(f"  - 学生:{role_count['student']} 人 | 教师:{role_count['teacher']} 人 | 管理员:{role_count['admin']} 人")
        print(f"系统总课程数:{len(self.all_courses)}")
        for course in self.all_courses[:5]:  # 只显示前5个课程
            # 修改这行,添加对teacher是否为None的检查
            teacher_name = course.teacher.username if course.teacher else "未分配"
            print(f"  - {course.course_name}(教师:{teacher_name})")
        if len(self.all_courses) > 5:
            print(f"  ... 还有 {len(self.all_courses)-5} 个课程未显示")
        print("="*50)

    def to_dict(self):
        """管理员类转换为字典以便序列化"""
        # 先调用父类方法获取基础属性
        result = super().to_dict()
        # 添加管理员专属属性
        result.update({
            "admin_id": self.admin_id
        })
        
        # 系统用户和课程通常由专门的加载/保存机制处理,这里不需要序列化
        return result

    # ------------------------------
    # 管理员专属方法:用户管理(增删用户)
    # ------------------------------
    def add_user(self, user):
        """添加用户到系统:user 为 Student/Teacher/Administrator 实例"""
        # 1. 验证:用户是否已存在(通过 user_id 唯一标识)
        for existing_user in self.system_users:
            if existing_user.user_id == user.user_id:
                print(f"用户已存在(ID:{user.user_id}),无法重复添加!")
                return False
        # 2. 添加到系统用户列表
        self.system_users.append(user)
        print(f"成功添加用户:{user.username}(角色:{user.role} | ID:{user.user_id})")
        return True

    def delete_user(self, user_id):
        """通过 user_id 删除系统用户"""
        # 1. 查找用户
        target_user = None
        for user in self.system_users:
            if user.user_id == user_id:
                target_user = user
                break
        if not target_user:
            print(f"未找到用户(ID:{user_id}),无法删除!")
            return False
        
        try:
            # 2. 处理关联数据
            if isinstance(target_user, Teacher):
                # 教师被删除:处理其管理的课程
                for course in list(target_user.managed_courses):
                    # 移除课程关联
                    course.teacher = None  # 或分配给其他教师
                    target_user.managed_courses.remove(course)
                    
                    # 处理由该教师创建的作业
                    for assignment in list(target_user.created_assignments):
                        if hasattr(assignment, 'course'):
                            assignment.course.remove_assignment(assignment) if hasattr(assignment.course, 'remove_assignment') else None
                target_user.created_assignments.clear()
            elif isinstance(target_user, Student):
                # 学生被删除:从所有已选课程中移除
                for course in list(target_user.enrolled_courses):
                    # 从课程中移除学生
                    if target_user in course.enrolled_students:
                        course.enrolled_students.remove(target_user)
                    # 从学生中移除课程
                    target_user.enrolled_courses.remove(course)
                    
                    # 清理成绩记录
                    if hasattr(self, 'lms') and hasattr(self.lms, 'grading_system'):
                        if course.course_id in self.lms.grading_system.grade_records:
                            if target_user.student_id in self.lms.grading_system.grade_records[course.course_id]:
                                del self.lms.grading_system.grade_records[course.course_id][target_user.student_id]
                target_user.grades.clear()
                target_user.submitted_assignments.clear()
            
            # 3. 从系统用户列表中删除
            self.system_users.remove(target_user)
            
            # 4. 同时从全局用户列表中删除该用户
            if target_user in User._all_users:
                User._all_users.remove(target_user)
                
            print(f"成功删除用户:{target_user.username}(ID:{user_id})")
            return True
        except Exception as e:
            print(f"删除用户时出错: {e}")
            return False

    # ------------------------------
    # 管理员专属方法:课程审核与系统统计
    # ------------------------------
    def approve_course(self, course):
        """审核课程:通过后添加到系统总课程列表并更新状态"""
        # 导入Course类以避免未定义错误
        from Course_Management_and_Enrollment.course_task_classes import Course
        
        if course in self.all_courses:
            print(f"课程 {course.course_name} 已审核,无需重复操作!")
            return False
        # 1. 审核逻辑:检查课程名称是否合法
        if not course.course_name or len(course.course_name) < 2:
            print(f"审核失败:课程名称 {course.course_name} 不合法(需至少2个字符)")
            return False
        # 2. 审核通过:添加到系统总课程列表
        self.all_courses.append(course)
        # 确保更新课程状态为已审核
        course.status = "approved"

        if course not in Course._all_courses:
            Course._all_courses.append(course)

        print(f"课程 {course.course_name}(ID:{course.course_id})审核通过,已加入系统!")
        return True

    def view_system_stats(self):
        """查看系统详细统计(比仪表盘更详细)"""
        print("="*60)
        print("【系统详细统计】")
        # 1. 用户统计
        print("\n1. 用户统计:")
        role_count = {"student": 0, "teacher": 0, "admin": 0}
        for user in self.system_users:
            role_count[user.role] += 1
        print(f"   - 总用户数:{sum(role_count.values())}")
        print(f"   - 学生:{role_count['student']} 人 | 教师:{role_count['teacher']} 人 | 管理员:{role_count['admin']} 人")
        # 2. 课程统计
        print("\n2. 课程统计:")
        if not self.all_courses:
            print("   - 暂无课程")
        else:
            avg_students = sum(len(c.enrolled_students) for c in self.all_courses) / len(self.all_courses)
            print(f"   - 总课程数:{len(self.all_courses)}")
            print(f"   - 平均每课程学生数:{avg_students:.1f}")
            # 统计有作业的课程数
            courses_with_assignments = 0
            total_assignments = 0
            for course in self.all_courses:
                if course.course_assignments:
                    courses_with_assignments += 1
                    total_assignments += len(course.course_assignments)
            print(f"   - 有作业的课程数:{courses_with_assignments}(总作业数:{total_assignments})")
        print("="*60)

    def sync_all_courses(self, all_system_courses):
        """同步all_courses列表与系统中所有已批准的课程"""
        # 清空当前all_courses列表
        self.all_courses.clear()
        # 重新添加所有状态为approved的课程
        for course in all_system_courses:
            if hasattr(course, 'status') and course.status == "approved":
                self.all_courses.append(course)
        print(f"已同步 {len(self.all_courses)} 个已批准课程到管理员all_courses列表")


# 测试代码:仅在直接运行该文件时执行
if __name__ == "__main__":
    from utils import generate_id
    
    # 1. 测试 Student 类
    print("="*30 + " 测试 Student 类 " + "="*30)
    stu1 = Student(user_id=generate_id("USER"), username="stu001", password="123456", email="stu001@xxx.com", role="student")
    stu1.login("stu001", "123456")  # 登录测试 - 修复:使用位置参数
    stu1.view_dashboard()  # 仪表盘测试
    
    # 使用Mock类替代跨模块导入
    class MockCourse:
        def __init__(self, course_id, course_name, max_students):
            self.course_id = course_id
            self.course_name = course_name
            self.max_students = max_students
            self.enrolled_students = []
            self.course_assignments = []
    
    course1 = MockCourse(course_id="COURSE_001", course_name="Python OOP", max_students=20)
    stu1.enroll_course(course1)  # 选课测试
    stu1.view_my_progress(course1)  # 进度查看测试

    # 2. 测试 Teacher 类
    print("\n" + "="*30 + " 测试 Teacher 类 " + "="*30)
    tch1 = Teacher(user_id=generate_id("USER"), username="tch001", password="654321", email="tch001@xxx.com")
    tch1.login("tch001", "654321")  # 修复:使用位置参数
    tch1.view_dashboard()
    
    # 修改Teacher的create_course方法调用,避免跨模块导入
    # 只测试基本功能,不测试跨模块功能
    print("教师创建课程功能需要系统集成测试")

    # 3. 测试 Administrator 类
    print("\n" + "="*30 + " 测试 Administrator 类 " + "="*30)
    admin1 = Administrator(user_id=generate_id("USER"), username="admin001", password="admin123", email="admin001@xxx.com")
    admin1.add_user(stu1)  # 添加学生用户
    admin1.add_user(tch1)  # 添加教师用户
    admin1.view_dashboard()  # 管理员仪表盘
    admin1.view_system_stats()  # 系统统计
